home *** CD-ROM | disk | FTP | other *** search
/ SGI Developer Toolbox 6.1 / SGI Developer Toolbox 6.1 - Disc 4.iso / src / exampleCode / opengl / xlib / zrgb.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-08-02  |  13.9 KB  |  444 lines

  1. /*
  2.  * Copyright 1993, 1994, Silicon Graphics, Inc.
  3.  * All Rights Reserved.
  4.  *
  5.  * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Silicon Graphics, Inc.;
  6.  * the contents of this file may not be disclosed to third parties, copied or
  7.  * duplicated in any form, in whole or in part, without the prior written
  8.  * permission of Silicon Graphics, Inc.
  9.  *
  10.  * RESTRICTED RIGHTS LEGEND:
  11.  * Use, duplication or disclosure by the Government is subject to restrictions
  12.  * as set forth in subdivision (c)(1)(ii) of the Rights in Technical Data
  13.  * and Computer Software clause at DFARS 252.227-7013, and/or in similar or
  14.  * successor clauses in the FAR, DOD or NASA FAR Supplement. Unpublished -
  15.  * rights reserved under the Copyright Laws of the United States.
  16.  */
  17. /*
  18.  *   zrgb.c:  an openGL-Xlib RGB, zbuffer example program.
  19.  *
  20.  *              zrgb is the openGL "after" version of the IrisGL
  21.  *              "before" program, ~4Dgifts/examples/grafix/zrgb.c
  22.  *
  23.  *            - LEFTMOUSE:  move the 3 polygons around a center
  24.  *            - Esc key:  exit
  25.  * 
  26.  *    This program demostrates zbuffering 3 intersecting RGB polygons while
  27.  *  in doublebuffer mode where, movement of the mouse with the LEFTMOUSE
  28.  *  button depressed will, rotate the 3 polygons via compound rotations 
  29.  *  allowing continuous screen-oriented rotations.  (See orient(), and 
  30.  *  draw_scene() below).  Notice that there is no wasted CPU usage when the 
  31.  *  user moves the mouse out of the window without holding down LEFTMOUSE--
  32.  *  there is no "qtest" -type functionality being performed.  Hence the 
  33.  *  program simply blocks on the XNextEvent statement.
  34.  *
  35.  *                                   ratmandu -- ported to openGL, april 93
  36.  */
  37.  
  38. #include <GL/glx.h>
  39. #include <stdio.h>
  40. #include <stdlib.h>
  41. #include <X11/keysym.h>
  42. #include <X11/Xlib.h>
  43. #include <X11/Xutil.h>
  44.  
  45. #define TRUE            1
  46. #define FALSE           0
  47.  
  48.  
  49. Display *dpy;                                    /* The X server connection */
  50. Atom del_atom;                                   /* WM_DELETE_WINDOW atom   */
  51. Window glwin;                                    /* handle to the GL window */
  52. XEvent event;
  53.  
  54. /* function declarations */
  55.  
  56. void openwindow(char *);
  57. void resize_buffer(void);
  58. void clean_exit(void);
  59. void initGL(void);
  60. void orient(void);
  61. void drawScene(void);
  62. void drawPolys(void);
  63.  
  64. static float objmat[16] = {
  65.          1.0, 0.0, 0.0, 0.0,
  66.          0.0, 1.0, 0.0, 0.0,
  67.          0.0, 0.0, 1.0, 0.0,
  68.          0.0, 0.0, 0.0, 1.0,
  69. };
  70.  
  71. int xsize, ysize;                        /* current size-of-window keepers */
  72. double scrnaspect;                                   /* aspect ratio value */
  73. int xpos, ypos, oxpos, oypos;                /* old and new mouse position */
  74.  
  75.  
  76.  
  77. main(argc,argv)
  78. int argc;
  79. char **argv;
  80. {
  81.     int myExpose, myConfigure, myButtPress, myKeyPress; 
  82.     int needToDraw = 0;                  /* don't set this to true until
  83.                                              we get our first Expose event */
  84.  
  85.  
  86.  
  87.     myExpose = myConfigure = myButtPress = myKeyPress = FALSE;
  88.  
  89.     openwindow(argv[0]);
  90.    
  91.   
  92.    /* start out making the singlebuffer window be our current GL window */
  93.     initGL();                                          /* do GL init stuff */
  94.  
  95.     /*
  96.      * The event loop.
  97.      */
  98.     while (1) {         /* standard logic:  get event(s), process event(s) */
  99.  
  100.         XEvent event;
  101.         KeySym keysym;
  102.         char buf[4];
  103.  
  104.     /* this "do while" loop does the `get events' half of the "get events,
  105.      *  process events" action of the infinite while.  this is to ensure
  106.      *  the event queue is always drained before the events that have come
  107.      *  in are processed.
  108.      */
  109.         do {
  110.  
  111.             XNextEvent(dpy, &event);
  112.             switch (event.type) {
  113.  
  114.             /* "Expose" events are sort of like "REDRAW" in gl-speak in
  115.              *  terms of when a window becomes visible, or a previously
  116.              *  invisible part becomes visible.
  117.              */
  118.                 case Expose:                        /* Exposures */
  119.                     needToDraw = myExpose = TRUE;
  120.                     break;
  121.  
  122.             /* "ConfigNotify" events are like "REDRAW" in terms of changes
  123.              *   to a window's size or position.
  124.              */
  125.                 case ConfigureNotify:                /* Resize GL manually */
  126.                     xsize = event.xconfigure.width;
  127.                     ysize = event.xconfigure.height;
  128.                     needToDraw = myConfigure = TRUE;
  129.                     break;
  130.  
  131.             /* Wait for "MotionNotify" events so the queue doesn't fill up
  132.              */
  133.                 case MotionNotify:                        
  134.                     myButtPress = TRUE;
  135.                     xpos = event.xmotion.x;
  136.                     ypos = event.xmotion.y;
  137.                     break;
  138.  
  139.             /* "ClientMessage" is generated if the WM itself is being
  140.              *  gunned down and sends an exit signal to any running prog.
  141.              */
  142.                 case ClientMessage:
  143.                     if (event.xclient.data.l[0] == del_atom)
  144.                         clean_exit();
  145.                     break;
  146.  
  147.             /* "KeyPress" events are those that would be generated before
  148.              *   whenever queueing up any KEYBD key via qdevice.
  149.              */
  150.                 case KeyPress:
  151.                    /* save out which unmodified key (i.e. the  key was
  152.                     *  not modified w/something like "Shift", "Ctrl",
  153.                     *  or "Alt") got pressed for use below.
  154.                     */
  155.                     XLookupString((XKeyEvent *)&event, buf, 4, &keysym, 0);
  156.                     myKeyPress = TRUE;
  157.                     break;
  158.  
  159.               }  /* end switch (event.type) */
  160.  
  161.  
  162.         } while (XPending(dpy));   /* end "do { } while".
  163.                                     * XPending() is like qtest()--it only
  164.                                     * tells you if there're any events
  165.                                     * presently in the queue.  it does not
  166.                                     * disturb queue's contents in any way.
  167.                                     */
  168.  
  169.     /* On an "Expose" event, redraw the affected pop'd or de-iconized window
  170.      */
  171.         if (myExpose) {
  172.             resize_buffer();   
  173.             myExpose = FALSE;               /* reset flag--queue now empty */
  174.         }
  175.  
  176.     /* On a "ConfigureNotify" event, the GL window has either been moved or
  177.      *  resized.  Respond accordingly and then redraw its contents.
  178.      */
  179.         if (myConfigure) {
  180.             oxpos = xpos;
  181.             oypos = ypos;
  182.             resize_buffer();   
  183.             myConfigure = FALSE;            /* reset flag--queue now empty */
  184.         }
  185.  
  186.         if (needToDraw) {
  187.             drawScene();
  188.             needToDraw = FALSE;
  189.         }
  190.  
  191.         /* On a keypress of Esc key, exit program.
  192.          */
  193.         if (myKeyPress) {
  194.             if (keysym == XK_Escape)
  195.                 clean_exit();
  196.         }
  197.  
  198.         if (myButtPress) {
  199.             orient();
  200.             drawScene();
  201.             myButtPress = FALSE;
  202.         }
  203.     }      /* end while(1) */
  204.  
  205. }      /* end main */
  206.  
  207.  
  208.  
  209. static int attributeList[] = { GLX_RGBA, 
  210.                                GLX_DOUBLEBUFFER, 
  211.                                GLX_RED_SIZE, 1, 
  212.                                GLX_GREEN_SIZE, 1, 
  213.                                GLX_BLUE_SIZE, 1,
  214.                    GLX_DEPTH_SIZE, 1,
  215.                                None };
  216. static int attributeList2[] = { GLX_RGBA,
  217.                                GLX_RED_SIZE, 1,
  218.                                GLX_GREEN_SIZE, 1,
  219.                                GLX_BLUE_SIZE, 1,
  220.                                GLX_DEPTH_SIZE, 1,
  221.                                None };
  222.  
  223.  
  224. static Bool WaitForNotify(Display *d, XEvent *e, char *arg) {
  225.     return (e->type == MapNotify) && (e->xmap.window == (Window)arg);
  226. }
  227.  
  228. XSizeHints Winhints;                          /* used to fix window size */
  229.  
  230.  
  231. /*  openwindow -
  232.  *     establish connection to X server, get screen info, specify the
  233.  *     attributes we want the WM to try to provide, and create the GL window
  234.  */
  235. void openwindow(char *progname) {
  236.  
  237.     XVisualInfo *vi;
  238.     GLXContext cx;
  239.     Colormap cmap;
  240.     XSizeHints Winhints;                          /* used to fix window size */
  241.     XSetWindowAttributes swa;
  242.     int scrnnum;                               /* X screen number            */
  243.     int xorig, yorig;                          /* window (upper-left) origin */
  244.     long scrnheight;
  245.  
  246.  
  247.  
  248.  
  249.    /* define window initial size */
  250.     xorig = 50;  yorig = 40;
  251.     xsize = 300; ysize = 240;
  252.     scrnaspect = xsize / (double) ysize;
  253.  
  254.    /* Connect to the X server and get screen info */
  255.     if ((dpy = XOpenDisplay(NULL)) == NULL) {
  256.         fprintf(stderr, "%s: cannot connect to X server %s\n",
  257.                                  progname, XDisplayName(NULL));
  258.         exit(1);
  259.     }
  260.  
  261.     scrnnum = DefaultScreen(dpy);
  262.     scrnheight = DisplayHeight(dpy, scrnnum);
  263.  
  264.         /* get an appropriate visual */
  265.     vi = glXChooseVisual(dpy, DefaultScreen(dpy), attributeList);
  266.     if (vi == NULL) {
  267.         fprintf(stderr, "Unable to obtain Doublebuffered visual;  ");
  268.         fprintf(stderr, "now going for singlebuffer'd...\n");
  269.     vi = glXChooseVisual(dpy, DefaultScreen(dpy), attributeList2);
  270.     }
  271.     if (vi == NULL) {
  272.         printf("Unable to obtain Singlebuffered VISUAL(????)\n");
  273.         exit(0);
  274.     }
  275.  
  276.     /* create a GLX context */
  277.     cx = glXCreateContext(dpy, vi, None, GL_TRUE);
  278.  
  279.     /* create a colormap */
  280.     cmap = XCreateColormap(dpy, RootWindow(dpy, vi->screen),
  281.                            vi->visual, AllocNone);
  282.  
  283.     /* create a window */
  284.     swa.colormap = cmap;
  285.     swa.border_pixel = 0;
  286.     swa.event_mask = StructureNotifyMask  | ButtonPressMask | ExposureMask |
  287.          Button1MotionMask | KeyPressMask;    /* express interest in events */;
  288.     glwin = XCreateWindow(dpy, RootWindow(dpy, vi->screen),
  289.                           xorig, yorig, xsize, ysize, 
  290.                           0, vi->depth, InputOutput, vi->visual,
  291.                           CWBorderPixel|CWColormap|CWEventMask, &swa);
  292.  
  293.     XMapWindow(dpy, glwin);
  294.     XIfEvent(dpy, &event, WaitForNotify, (char*)glwin);
  295.  
  296.     /* connect the context to the window */
  297.     glXMakeCurrent(dpy, glwin, cx);
  298.  
  299.     if (!(glwin)) {
  300.         fprintf(stderr,"%s: couldn't create \"parent\" X window\n",progname);
  301.         exit(1);
  302.     }
  303.  
  304.    /* define string that will show up in the window title bar (and icon) */
  305.     XStoreName(dpy, glwin, "z-buffered rgb program");
  306.  
  307.    /* specify the values for the Window Size Hints we want to enforce:  this
  308.     *  window's aspect ratio needs to stay at 1:1, constrain min and max
  309.     *  window size, and specify the initial size of the window.
  310.     */
  311.     Winhints.width  = xsize;          /* specify desired x/y size of window */
  312.     Winhints.height = ysize;
  313.     Winhints.min_width = xorig;                       /* define min and max */
  314.     Winhints.max_width = scrnheight-1;                /* width and height   */
  315.     Winhints.min_height = yorig;
  316.     Winhints.max_height = scrnheight-1;
  317.     Winhints.min_aspect.x = xsize;    /* keep aspect to a xsize:ysize ratio */
  318.     Winhints.max_aspect.x = xsize;
  319.     Winhints.min_aspect.y = ysize;
  320.     Winhints.max_aspect.y = ysize;
  321.     Winhints.flags = USSize|PMaxSize|PMinSize|PAspect;           /* set the */
  322.     XSetNormalHints(dpy, glwin, &Winhints);      /* corresponding flags */
  323.  
  324.    /* express interest in WM killing this app */
  325.     if ((del_atom = XInternAtom(dpy, "WM_DELETE_WINDOW", True)) != None)
  326.         XSetWMProtocols(dpy, glwin, &del_atom, 1);
  327.  
  328.     return ;
  329. }
  330.  
  331.  
  332.  
  333.  
  334. /*  window has been moved or resized so update viewport & CTM stuff.
  335.  */
  336. void resize_buffer() {
  337.  
  338.     XSync(dpy, False);  /* STILL NEED THIS????? *//* Need before GL reshape */
  339.     scrnaspect = xsize / (double) ysize;
  340.     glViewport(0, 0, xsize-1, ysize-1);
  341. }
  342.  
  343.  
  344.  
  345. /*  clean up before exiting
  346.  */
  347. void clean_exit(void)
  348. {
  349.     XCloseDisplay(dpy);
  350.     exit(0);
  351. }
  352.  
  353.  
  354.  
  355. /* setup all necessary GL initialzation parameters.
  356.  */
  357. void initGL()
  358. {
  359.     glEnable(GL_DEPTH_TEST);
  360.     glClearColor(0.16, 0.39, 0.78, 0.0);
  361.     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  362.     glLoadIdentity();
  363.     gluPerspective(400.0, scrnaspect, 30.0, 1000.0);
  364. }
  365.  
  366.  
  367. void orient() 
  368. {
  369.     float dx, dy;
  370.  
  371.     glPushMatrix();
  372.     dx = xpos-oxpos;
  373.     dy = oypos-ypos;
  374.     glLoadIdentity();
  375.     glRotatef((float) (0.03*(xpos-oxpos)), 1.0, 0.0, 0.0);
  376.     glRotatef((float) (0.03*(oypos-ypos)), 0.0, 1.0, 0.0);
  377.     glMultMatrixf(objmat);
  378.     glGetFloatv(GL_MODELVIEW_MATRIX, objmat);
  379.  
  380.     glPopMatrix();
  381. }
  382.  
  383.  
  384. void drawScene() 
  385. {
  386.     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  387.  
  388.     glPushMatrix();
  389.     glTranslatef(0.0, 0.0, -40.0);
  390.     glMultMatrixf(objmat);
  391.     glRotatef(-220.0, 0.0, 1.0, 0.0);  /* skews orig view to show all polys */
  392.     drawPolys();
  393.     glPopMatrix();
  394.     glFlush ();
  395.     glXSwapBuffers(dpy, glwin);
  396. }
  397.  
  398.  
  399. float polygon1[3][3] = { {-10.0, -10.0,   0.0,},
  400.                          { 10.0, -10.0,   0.0,},
  401.                          {-10.0,  10.0,   0.0,} };
  402.  
  403. float polygon2[3][3] = { {  0.0, -10.0, -10.0,},
  404.                          {  0.0, -10.0,  10.0,},
  405.                          {  0.0,   5.0, -10.0,} };
  406.  
  407. float polygon3[4][3] = { {-10.0,   6.0,   4.0,},
  408.                          {-10.0,   3.0,   4.0,},
  409.                          {  4.0,  -9.0, -10.0,},
  410.                          {  4.0,  -6.0, -10.0,} };
  411.  
  412. void drawPolys() 
  413. {
  414.     glBegin(GL_POLYGON);
  415.     glColor4f(0.0, 0.0, 0.0, 0.0);
  416.     glVertex3fv(&polygon1[0][0]);
  417.     glColor4f(0.5, 0.5, 0.5, 0.0);
  418.     glVertex3fv(&polygon1[1][0]);
  419.     glColor4f(1.0, 1.0, 1.0, 0.0);
  420.     glVertex3fv(&polygon1[2][0]);
  421.     glEnd();
  422.  
  423.     glBegin(GL_POLYGON);
  424.     glColor4f(1.0, 1.0, 0.0, 0.0);
  425.     glVertex3fv(&polygon2[0][0]);
  426.     glColor4f(0.0, 1.0, 0.5, 0.0);
  427.     glVertex3fv(&polygon2[1][0]);
  428.     glColor4f(0.0, 0.0, 1.0, 0.0);
  429.     glVertex3fv(&polygon2[2][0]);
  430.     glEnd();
  431.  
  432.     glBegin(GL_POLYGON);
  433.     glColor4f(1.0, 1.0, 0.0, 0.0);
  434.     glVertex3fv(&polygon3[0][0]);
  435.     glColor4f(1.0, 0.0, 1.0, 0.0);
  436.     glVertex3fv(&polygon3[1][0]);
  437.     glColor4f(0.0, 0.0, 1.0, 0.0);
  438.     glVertex3fv(&polygon3[2][0]);
  439.     glColor4f(1.0, 0.0, 1.0, 0.0);
  440.     glVertex3fv(&polygon3[3][0]);
  441.     glEnd();
  442.  
  443. }
  444.